package com.mai4j.maiadmin.service.impl;

import com.mai4j.maiadmin.misc.DbUtils;
import com.mai4j.maiadmin.model.dto.PageDTO;
import com.mai4j.maiadmin.model.dto.UserGroupDTO;
import com.mai4j.maiadmin.model.http.datatables.Datatable;
import com.mai4j.maiadmin.model.http.datatables.Search;
import com.mai4j.maiadmin.service.AdminMenuService;
import com.mai4j.maiadmin.service.UserGroupService;
import com.mai4j.maiadmin.support.JooqProvider;
import com.mai4j.maiadmin.support.i18n.I18n;
import org.apache.commons.lang3.StringUtils;
import org.jooq.Condition;
import org.jooq.DSLContext;
import org.jooq.Record8;
import org.jooq.SelectOnConditionStep;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

import static com.mai4j.maiadmin.generated.Tables.USER_GROUP_DESCRIPTION;
import static com.mai4j.maiadmin.generated.tables.UserGroup.USER_GROUP;

/**
 * 微信公众号请关注: 开源螺丝钉
 * <br>
 * 码云请关注: <a href="https://gitee.com/xiyoufang">https://gitee.com/xiyoufang</a>
 * <br>
 * 哔哩哔哩请关注: <a href="https://space.bilibili.com/438927834">https://space.bilibili.com/438927834</a>
 *
 * @author xiyoufang
 */
@Service
public class UserGroupServiceImpl implements UserGroupService {

    private final AdminMenuService adminMenuService;

    public UserGroupServiceImpl(AdminMenuService adminMenuService) {
        this.adminMenuService = adminMenuService;
    }

    @Cacheable(value = "data", key = "'usergroup:' + #userGroupId + ':' + #languageCode")
    @Override
    public UserGroupDTO get(Long userGroupId, String languageCode) {
        return JooqProvider.dsl()
                .select(USER_GROUP.USER_GROUP_ID,
                        USER_GROUP.GROUP_CODE,
                        USER_GROUP.PERMISSION,
                        USER_GROUP.DATE_ADDED,
                        USER_GROUP.DATE_MODIFIED,
                        USER_GROUP_DESCRIPTION.NAME,
                        USER_GROUP_DESCRIPTION.DESCRIPTION
                )
                .from(USER_GROUP)
                .leftJoin(USER_GROUP_DESCRIPTION)
                .on(USER_GROUP.USER_GROUP_ID.eq(USER_GROUP_DESCRIPTION.USER_GROUP_ID)
                        .and(USER_GROUP_DESCRIPTION.LANGUAGE_CODE.eq(languageCode)))
                .where(USER_GROUP.USER_GROUP_ID.eq(userGroupId)).fetchOneInto(UserGroupDTO.class);
    }

    @Override
    public PageDTO<UserGroupDTO> paginate(Datatable datatable) {
        DSLContext dsl = JooqProvider.dsl();
        SelectOnConditionStep<Record8<Long, String, String, Long, LocalDateTime, LocalDateTime, String, String>> query = dsl.select(USER_GROUP.USER_GROUP_ID,
                        USER_GROUP.GROUP_CODE,
                        USER_GROUP.PERMISSION,
                        USER_GROUP.ADMIN_MENU_ID,
                        USER_GROUP.DATE_ADDED,
                        USER_GROUP.DATE_MODIFIED,
                        USER_GROUP_DESCRIPTION.NAME,
                        USER_GROUP_DESCRIPTION.DESCRIPTION)
                .from(USER_GROUP)
                .leftJoin(USER_GROUP_DESCRIPTION)
                .on(USER_GROUP.USER_GROUP_ID.eq(USER_GROUP_DESCRIPTION.USER_GROUP_ID).and(USER_GROUP_DESCRIPTION.LANGUAGE_CODE.eq(I18n.getTag())));
        String value = Optional.ofNullable(datatable.getSearch()).orElse(new Search()).getValue();
        List<Condition> conditions = new ArrayList<>();
        if (StringUtils.isNotBlank(value)) {
            value = "%" + value + "%";
            conditions.add(USER_GROUP.GROUP_CODE.like(value).or(USER_GROUP_DESCRIPTION.NAME.like(value)).or(USER_GROUP_DESCRIPTION.DESCRIPTION.like(value)));
        }
        query.where(conditions);
        int count = dsl.fetchCount(query);
        List<UserGroupDTO> userGroupDTOS = count == 0 ? Collections.emptyList() : query
                .orderBy(USER_GROUP.USER_GROUP_ID)
                .limit(datatable.getStart(), datatable.getLength())
                .fetchInto(UserGroupDTO.class);
        userGroupDTOS.forEach(r -> r.setAdminMenu(adminMenuService.get(r.getAdminMenuId())));
        return new PageDTO<>(userGroupDTOS, DbUtils.getPage(datatable), datatable.getLength(), DbUtils.getTotalPage(count, datatable), count);
    }
}
